import time, json
import requests
import math, hashlib


class order_form:
    def __init__(self, db, cursor):
        self.appkey = "1bN0kRdX8DVPGGvD5UdP"
        self.appSecret = "LzHQEv5nH8umSviagRdhK3lAJrYSMJpqe8QDuO8o"
        self.openid = "kjvb46f04fZ4uHQAbBBM"
        self.api = "https://gateway.rjmart.cn/open/shop"
        self.pre_api = "https://gateway.test.rj-info.com/open/shop"
        self.db = db
        self.cursor = cursor
        self.status = {
            # "0": "待对接方确认",
            # "-1": "对接失效",
            "3": "订单关闭",
            "4": "未发货",
            "5": "未开票",
            # "6": "待结算",
            # "7": "已评价",
            # "8": "待确认",
            "9": "采购人申请取消",
            # "10": "结算中",
            # "11": "完成",
            # "12": "结算审批",
            # "13": "结算付款",
            "15": "未回款",
            # "16": "待结算经费",
            # "17": "结算经费失败",
            "19": "供应商申请取消",
            # "20": "订单验收审批",
            # "21": "统一报帐人驳回",
            # "22": "待设备处验收审核",
        }
        self.DB_TABLE_NAME = {
            # "辰星销售台账": ["辰星销售台账", {"startTime": "2024-01-01 00:00:00"}],
            "CxOrder": ["CxOrder", {}],
        }
        self.Skip_Status = ["订单关闭", "采购人申请取消", "供应商申请取消"]

    # 数据库操作
    def ins_del_upd(
        self, sql: str
    ) -> (bool, dict):  # type:ignore #!数据库添加、删除、修改
        try:
            rowcount = self.cursor.execute(sql)
            self.db.commit()
            print("{}操作成功".format(sql.split()[0]))
            return True, {"rowcount": rowcount}
        except Exception as e:
            print("操作失败：{}".format({"error": e, "sql": sql}))
            self.db.rollback()
            return False, {"error": e, "sql": sql}

    # 数据库查询
    def select(self, sql: str) -> (bool, dict):  # type:ignore #!数据搜索
        try:
            # 执行SQL语句
            self.cursor.execute(sql)
            # 获取所有记录列表
            results = self.cursor.fetchall()
            self.db.commit()
            return True, results
        except Exception as e:
            return False, {"error": e, "sql": sql}

    # 获取Authorization_Code
    def get_Authorization_Code(self):
        url = "https://www.rjmart.cn/auth/oauth/authorize"
        response = requests.get(url=url)
        return response

    # 通过Authorization_Code获取Access_Token
    def ac_get_Access_Token(self):
        url = "https://www.rjmart.cn/auth/oauth/token"
        response = requests.post(url=url)
        return response

    # 通过openid获取Access_Token
    def openid_Access_Token(self):
        """通过openid获取Access_Token"""
        url = "https://www.rjmart.cn/auth/openid/login"
        md5 = hashlib.md5()
        md5.update(self.appSecret.encode("utf-8"))  # 指定需要加密的字符串
        sign = md5.hexdigest()  # 加密后的字符串
        data = {"openid": self.openid, "sign": sign}
        response = requests.post(url=url, data=data)
        results = json.loads(response.content.decode("utf-8"))
        t = time.time()
        results.update({"time": t})
        print(results)
        with open("Access_Token.json", mode="w") as f:
            f.write(json.dumps(results))
        return results

    # 查询单个商品内容（id）
    def ProductDetail(self, ProductId):
        url = "/openapi/product/queryProductDetail"
        name = "ProductDetail" + str(ProductId)
        data = json.dumps({"id": ProductId})
        return self.no_data(url, name, data=data)

    # api基础模板
    def no_data(self, url, name, data=""):
        time_now = time.time()
        with open("Access_Token.json") as j:
            ac_json = json.load(j)
        with open(f"./out/req/{name}.json", mode="w", encoding="utf-8") as f:
            f.write(data)
        Access_Token = ac_json["access_token"]
        time_acc = ac_json["time"]
        if time_now - time_acc > 600:
            Access_Token = self.openid_Access_Token()["access_token"]
        header = {
            "Authorization": f"Bearer {Access_Token}",
            "Content-Type": "application/json;charset=utf-8",
        }
        json_post_data = self.appSecret + data
        # data = json.loads(data)
        md5 = hashlib.md5()
        md5.update(json_post_data.encode("utf-8"))  # 指定需要加密的字符串
        sign = md5.hexdigest()  # 加密后的字符串
        s_url = f"{self.api}{url}?appkey={self.appkey}&sign={sign}"
        response = requests.post(url=s_url, data=data.encode("utf-8"), headers=header)
        results = response.content.decode("utf-8")
        with open(f"./out/res/{name}.json", mode="w", encoding="utf-8") as f:
            f.write(results)
        return response

    #!page int 分页参数，第几页
    #!size int 分页参数，每页多少个（最多支持200条，size>200?200:size）
    # *orderNo string 订单号，只支持精确搜索
    # *buyuserName string 采购人
    # *departmentId int 采购部门id
    # *startTime string 开始时间，格式 yyyy-MM-dd HH:mm:ss
    # *endTime string 结束时间，格式 yyyy-MM-dd HH:mm:ss
    # *updateStartTime string 更新开始时间，格式 yyyy-MM-dd HH:mm:ss
    # *updateEndTime string 更新结束时间，格式 yyyy-MM-dd HH:mm:ss
    # *orderStatus int 订单状态
    # 值	描述
    # 8	    新订单
    # 5	    待收货
    # 40	待发货
    # 110	已完成
    # 80	待结算
    # *orgId int 采购单位id
    # *goodName string 商品名称
    def queryOrderPage(
        self, page: int = 1, size: int = 200, data: dict = dict()
    ) -> requests.Response:
        url = "/openapi/order/queryOrderPage"
        data_add = {
            "page": page,
            "size": size,
            # "orderNo":"DC202212032427101"
            # "updateStartTime": "{} 00:00:00".format(
            #     datetime.today().date() - timedelta(days=1)
            # ),
        }
        data_add.update(data)
        name = "ProductList" + "&".join(list(map(str, data.get("buyuserName", [""]))))
        return self.no_data(url, name, data=json.dumps(data_add))

    # !orderNo string 订单号，只支持精确搜索
    def getOrderByOrderNo(self, data: str = "") -> requests.Response:
        url = "/openapi/order/getOrderByOrderNo"
        name = "getOrderByOrderNo"
        for _ in range(10):
            time.sleep(1)
            if (
                "data"
                in (
                    resp := self.no_data(url=url, name=name, data=json.dumps(data))
                ).json()
                and resp.json()["data"]
            ):
                return resp
            print(resp.json())

        else:
            return self.no_data(url=url, name=name, data=json.dumps(data))

    def data_processing(self, process_type, data: dict = dict()):
        if process_type == "辰星销售台账":
            for i in range(len(data.copy()["openOrderDetailVoList"])):
                while True:
                    try:
                        with self.ProductDetail(  # ^获取分类id
                            data["openOrderDetailVoList"][i]["fgoodsId"]
                        ) as response:
                            data["openOrderDetailVoList"][i]["categoryname"] = (
                                a[0]["name"]
                                if (a := response.json()["data"]["category"])
                                else "商品已删除"
                            )
                        with self.getOrderByOrderNo(
                            {"orderNo": data["orderNo"]}  # type:ignore
                        ) as response:  # ^获取商品备注
                            data["openOrderDetailVoList"][i][
                                "suppRemark"
                            ] = response.json()["data"]["suppRemark"]
                        break
                    except:
                        pass
                self.Write_to_db(  # ^写入数据库
                    {
                        "下单日期": str(data["orderDate"]).split()[0],
                        "订单号": str(data["orderNo"]),
                        "采购单位": str(data["orgName"]),
                        "收货人": str(data["buyerName"]),
                        "商品名称": str(
                            data["openOrderDetailVoList"][i]["fgoodname"]
                        ).replace("'", "\\'"),
                        "商品分类": str(
                            data["openOrderDetailVoList"][i]["categoryname"]
                        ),
                        "品牌": str(data["openOrderDetailVoList"][i]["fbrand"]),
                        "货号": str(data["openOrderDetailVoList"][i]["fgoodcode"]),
                        "单位": str(data["openOrderDetailVoList"][i]["funit"]),
                        "规格": str(data["openOrderDetailVoList"][i]["fspec"]),
                        "数量": str(data["openOrderDetailVoList"][i]["fquantity"]),
                        "单价": str(data["openOrderDetailVoList"][i]["fbidprice"]),
                        "订单总价": str(data["totalPrice"]),
                        "备注": (
                            a
                            if (a := data["openOrderDetailVoList"][i]["suppRemark"])
                            else ""
                        ),
                    },
                    Table_Index=process_type,
                    status=self.status.get(str(data["status"]), "未知状态"),
                )
        elif process_type == "CxOrder":
            with self.getOrderByOrderNo(
                {"orderNo": data["orderNo"]}  # type:ignore
            ) as response:  # ^获取商品备注
                if "data" not in (data_json := response.json()):
                    return
                data["suppRemark"] = (
                    data_json["data"]["suppRemark"]
                    if data_json["data"] and "suppRemark" in data_json["data"]
                    else ""
                )
                data["contactphone"] = data_json["data"].get("contactphone", "")
                data["fbuyertelephone"] = data_json["data"].get("fbuyertelephone", "")
                data['address']=data_json['data'].get("address", "")
            ywcOrjsz=""
            for unitN in self.UnifiedSettlementUnit:
                if str(data["orgName"]).strip()==unitN["UnitName"].strip():
                    if data["status"]==11:
                        ywcOrjsz="已回款"
                        break
                    if data['status']==10:
                        ywcOrjsz=self.status['15']
                        break
            self.Write_to_db(  # ^写入数据库
                {
                    "OrderDate": str(data["orderDate"]).split()[0],
                    "OrderNo": str(data["orderNo"]),
                    "PurchasingUnit": str(data["orgName"]),
                    "DepartmentName":str(data["departmentName"]),
                    "ContactsName": str(data["buyerName"]),
                    "ContactsPhone": str(data.get("contactphone", "")),
                    "ConsigneePhone": str(data.get("fbuyertelephone", "")),
                    "ProductInfo": json.dumps(
                        data.get("openOrderDetailVoList", """{}"""),
                        ensure_ascii=False,
                    ).replace("'", "''").replace("\\n",""),
                    "Status": ywcOrjsz if ywcOrjsz else self.status.get(str(data["status"]),  (self.status['15'] if "已开票" in (a if (a := data["suppRemark"]) else "") else self.status['5'])),
                    "Price": str(data["totalPrice"]),
                    "Note": a if (a := data["suppRemark"]) else "",
                    "UrgeDate": str(data["orderDate"]).split()[0],
                    "ReceiptInfo":json.dumps(
                        data.get("address", """{}"""),
                        ensure_ascii=False,
                    ).replace("'", "''").replace("\\n","").replace("\\t","").replace("\n","").replace("\t",""),
                    **({
                        "ReceivedPayment":"是" 
                    } if ywcOrjsz=="已回款" else {})
                },
                Table_Index=process_type,
                status=self.status.get(str(data["status"]), "未知状态"),
            )

    def Write_to_db(self, data: dict = dict(), Table_Index: str = "", status: str = ""):
        if not Table_Index:
            return False
        if Table_Index == "辰星销售台账":
            sql = "SELECT COUNT(*) AS count FROM {} WHERE 订单号='{}' AND 货号='{}'".format(  # ^查询是否存在记录
                self.DB_TABLE_NAME[Table_Index][0], data["订单号"], data["货号"]
            )
        elif Table_Index == "CxOrder":
            sql = "SELECT COUNT(*) AS count FROM {} WHERE OrderNo='{}'".format(  # ^查询是否存在记录
                self.DB_TABLE_NAME[Table_Index][0], data["OrderNo"]
            )
        print(sql)
        if self.select(sql)[1][0]["count"] != 0:
            if Table_Index == "辰星销售台账":
                if status in self.Skip_Status:
                    sql = "DELETE FROM {} WHERE  订单号='{}'".format(
                        self.DB_TABLE_NAME[Table_Index][0], data["订单号"], data["货号"]
                    )  # type:ignore
                else:
                    sql = "UPDATE {} SET {} WHERE 订单号='{}' AND 货号='{}'".format(  # ^存在则修改
                        self.DB_TABLE_NAME[Table_Index][0],
                        ",".join(
                            [
                                "{}='{}'".format(i, data[i])
                                for i in data
                                if i != "订单号"
                            ]
                        ),
                        data["订单号"],
                        data["货号"],
                    )
            elif Table_Index == "CxOrder":
                if status in self.Skip_Status:
                    sql = "DELETE FROM {} WHERE  OrderNo='{}'".format(
                        self.DB_TABLE_NAME[Table_Index][0], data["OrderNo"]
                    )
                else:
                    sql = "UPDATE {} SET {} WHERE OrderNo='{}'".format(  # ^存在则修改
                        self.DB_TABLE_NAME[Table_Index][0],
                        ",".join(
                            [
                                "{}='{}'".format(i, data[i])
                                for i in data
                                if i != "OrderNo"
                            ]
                        ),
                        data["OrderNo"],
                    )
        else:
            if not status in self.Skip_Status:
                sql = "INSERT INTO {} ({}) VALUES ({})".format(  # ^不存在则添加
                    self.DB_TABLE_NAME[Table_Index][0],
                    ",".join(data.keys()),
                    ",".join(["'{}'".format(i) for i in data.values()]),
                )
        self.ins_del_upd(sql)

    def Urging(self):
        ok,self.UnifiedSettlementUnit=self.select("select * from UnifiedSettlementUnit")
        if not ok:
            return
        for process_type in self.DB_TABLE_NAME.values():
            data = self.queryOrderPage(data=process_type[1]).json()
            print(data["total"])
            for page in range(1, math.ceil(data["total"] / 200) + 1):
                for page_data in (
                    pages_data["data"]
                    if (
                        pages_data := self.queryOrderPage(
                            page=page, data=process_type[1]
                        ).json()["data"]
                    )
                    else []
                ):
                    self.data_processing(
                        data=page_data,
                        process_type=process_type[0],
                    )

    def main(self):
        self.Urging()


# if __name__ == "__main__":
#     mysql_server = {  #!数据库链接配置
#         "host": "127.0.0.1",
#         "user": "root",
#         "passwd": "GZCXSWKJFZYXGS",
#         "port": 3306,
#         "db": "order_list",
#         "cursorclass": pymysql.cursors.DictCursor,
#     }
#     try:
#         db = pymysql.connect(**mysql_server)
#         cursor = db.cursor()  #!创建数据游标
#         print("mysql连接成功！")
#     except Exception as e:
#         raise e
    
#     order_form(db=db, cursor=cursor).main()
